home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-09-25 | 47.2 KB | 1,828 lines | [TEXT/CWIE] |
- /*
- File: MoreControls.cp
-
- Contains:
-
- Written by: Pete Gontier (PCG)
-
- Copyright: Copyright (c) 1998 Apple Computer, Inc.
-
- Change History (most recent first):
-
- <4> 9/1/98 PCG Universal Headers 3.2
- <3> 7/24/98 PCG eliminate dependency on 'qd'
- <2> 7/21/98 PCG remove annoying assert in Get1NewStaticTextControl
- <2> 6/23/98 PCG add IsScrollBar
- <1> 6/16/98 PCG initial checkin
- */
-
-
- #include "MoreAppearance.h"
- #include "MoreControls.h"
-
- #include <Script.h>
- #include <MacWindows.h>
- #include <Resources.h>
-
- typedef struct
- {
- //
- // Used by AppendTabInfo and its callers.
- // Caches tab contents data temporarily.
- //
-
- Boolean enabled;
- ControlTabInfoRec ctir;
- }
- FullControlTabInfoRec, *FullControlTabInfoRecP, **FullControlTabInfoRecH;
-
- //
- // gControlScratchStr is used to relieve us from having to declare
- // a Str255 on the stack when we call GetResInfo and we don't care
- // about the name of the resource.
- //
-
- static Str255 gControlScratchStr;
-
- //
- // AssertControlHasDefProcResID is a macro which asserts that
- // a given control's control definition procedure resource has
- // a given resource ID. This is generally used to validate
- // assumptions about the data tags supported by a given
- // control definition procedure.
- //
-
- #if MORE_DEBUG
- static pascal Boolean MoreAssertControlHasDefProcResID
- (ControlHandle c, short requiredDPR)
- {
- SInt16 actualDPR;
-
- if (!MoreAssert (!GetControlDefProcResID (c,&actualDPR))) return false;
- if (!MoreAssert (actualDPR == requiredDPR)) return false;
-
- return true;
- }
- #else
- # define MoreAssertControlHasDefProcResID(c,requiredDPR) (true)
- #endif
-
- pascal OSErr GetControlDefProcResID (ControlHandle control, short *resID)
- {
- //
- // Given a control, determines what the resource ID of the control's
- // control definition procedure resource. If the resource has been
- // detached, this routine will fail and return an appropriate error.
- // Don't detach system definition procedure resources! Other people
- // may be using them as resources (expecting LoadResource to work, etc.)
- //
-
- ResType resType;
- GetResInfo ((**control).contrlDefProc, resID, &resType, gControlScratchStr);
- OSErr err = ResError ( );
- (void) MoreAssert (err || resType == kControlDefProcType);
- return err;
- }
-
- static pascal MoreControls_tAlignment FilterAlignment (MoreControls_tAlignment align)
- {
- //
- // If this function is passed MoreControls_kAlignSystem, it determines
- // what the correct alignment constant is based on the direction of the
- // system script. This way radio buttons on an Arabic system, whose
- // bubbles are on the right side, will align down the right edge without
- // the client program needing to know the details.
- //
-
- if (align == MoreControls_kAlignSystem)
- align = GetSysDirection ( ) == -1 ? MoreControls_kAlignRight : MoreControls_kAlignLeft;
-
- (void) MoreAssert (align == MoreControls_kAlignLeft ||
- align == MoreControls_kAlignCenter || align == MoreControls_kAlignRight);
-
- return align;
- }
-
- #pragma mark -
-
- static pascal OSErr AppendTabInfo
- (ControlHandle whichControl, UInt16 tabIndex,
- FullControlTabInfoRecP tabInfoP, FullControlTabInfoRecH tabInfoPackedArrayH)
- {
- OSErr err = noErr;
-
- //
- // For a given tab, this function gets the tab icon and string as
- // well whether the tab is enabled. Appends said data onto the end
- // of an array stored in a handle.
- //
- // This is a helper function. tabInfoP is supposed to have been allocated
- // by the caller, but the caller is not expected to care what's in it;
- // we do this so the caller can call AppendTabInfo in a loop without
- // this helper function repeatedly creating and destroying the buffer,
- // which would be slow, we presume. It's a classic case of optimizing without
- // first measuring.
- //
-
- if (!(MoreAssert (tabIndex && tabIndex <= GetControlMaximum (whichControl))))
- err = paramErr;
- else
- {
- Size actualSize;
-
- tabInfoP->ctir.version = 0;
-
- if (!(err = GetControlData (whichControl, tabIndex, kControlTabInfoTag,
- sizeof (tabInfoP->ctir), Ptr (&(tabInfoP->ctir)), &actualSize)))
- {
- if (!(err = GetControlData (whichControl, tabIndex, kControlTabEnabledFlagTag,
- sizeof (tabInfoP->enabled), Ptr (&(tabInfoP->enabled)), &actualSize)))
- {
- if (!MoreAssert (actualSize == sizeof (tabInfoP->enabled)))
- err = paramErr;
- else
- err = PtrAndHand (tabInfoP, Handle (tabInfoPackedArrayH), 1 + *(tabInfoP->ctir.name) + (sizeof (*tabInfoP) - sizeof (Str255)));
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr MoreGetControlRegion (ControlHandle control, RgnHandle *rgn)
- {
- //
- // Given a control, allocates and initializes a region describing the
- // control's bounds. Note this is different from (**control).contrlRect;
- // a control whose control definition function calls DrawThemeEditTextFrame
- // will (should) report its region as being 2 pixels larger than its contrlRect.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- if (!MoreAssert (control && *control && rgn))
- err = nilHandleErr;
- else
- {
- *rgn = NewRgn ( );
-
- if (!(err = QDError ( )))
- (void) SendControlMessage (control, calcCntlRgn, SInt32 (*rgn));
- }
-
- return err;
- }
-
- pascal OSErr InvalControl (ControlHandle control)
- {
- OSErr err = noErr;
-
- //
- // Given a control, invalidates the area occupied by the control.
- //
-
- if (!(MoreAssert (control && *control)))
- err = nilHandleErr;
- else
- {
- RgnHandle rgn;
-
- err = MoreGetControlRegion (control, &rgn);
-
- if (!err)
- {
- GrafPtr preservePort;
- GetPort (&preservePort);
- SetPort ((**control).contrlOwner);
- InvalRgn (rgn);
- SetPort (preservePort);
- DisposeRgn (rgn);
- }
- }
-
- return err;
- }
-
- pascal OSErr SetTabIcon (ControlHandle control, ControlPartCode part, short iconSuiteID)
- {
- OSErr err = noErr;
-
- //
- // This function demonstrates how to set the icon of a tab.
- // Unfortunately, under 1.0.X, the control definition won't
- // listen if the tab already has an icon which has been drawn.
- // We don't assert for this because it works if the tab has
- // no icon. Be careful.
- //
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else if (!MoreAssert (part >= GetControlMinimum (control)))
- err = paramErr;
- else if (!(MoreAssert (part <= GetControlMaximum (control))))
- err = paramErr;
- else
- {
- ControlTabInfoRec *ctirp = (ControlTabInfoRec *) NewPtr (sizeof (*ctirp));
-
- if (!ctirp)
- err = MemError ( );
- else
- {
- Size actualSize;
-
- ctirp->version = 0;
-
- if (!(err = GetControlData (control,part,kControlTabInfoTag,sizeof(ControlTabInfoRec),
- Ptr(ctirp),&actualSize)))
- {
- ctirp->iconSuiteID = iconSuiteID;
-
- err = SetControlData (control,part,kControlTabInfoTag,actualSize,Ptr(ctirp));
- }
-
- DisposePtr (Ptr (ctirp));
- (void) MoreAssert (noErr == MemError ( ));
- }
- }
-
- return err;
- }
-
- pascal OSErr CopyTabFontStyle (ControlHandle oldTabs, ControlHandle newTabs)
- {
- //
- // Copies the control font style data from one tab control to another.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssert (oldTabs && *oldTabs && newTabs && *newTabs))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (oldTabs,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (newTabs,kControlTabsDefProcResID))
- err = paramErr;
- else
- {
- ControlFontStyleRec cfsr;
- Size actualSize;
-
- if (!(err = GetControlData (oldTabs,kControlNoPart,kControlTabFontStyleTag,sizeof(cfsr),Ptr(&cfsr),&actualSize)))
- err = SetControlData (newTabs,kControlNoPart,kControlTabFontStyleTag,actualSize,Ptr(&cfsr));
- }
-
- return err;
- }
-
- static pascal OSErr DupTabsControl_Internal (ControlHandle old, ControlHandle *dup, UInt16 newControlMax)
- {
- //
- // This is a helper function containing common code to support
- // other exported functions. It creates a control with an
- // appropriate number of tabs, then embeds the control at
- // the same place in the hierarchy as the old control. This
- // function does not copy tab data from the old control to the
- // new control, though it does copy the style info.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssert (GetAppearanceVersion ( ) >= 0x0101))
- err = paramErr;
- else if (!MoreAssert (old && *old && dup))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (old,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssert (GetControlMaximum (old) <= newControlMax))
- err = paramErr;
-
- //
- // We assert that the old control is visible because there's a bug
- // in the tabs CDEF such that it won't write tab data into a non-visible
- // control. We copy tab data into the new control, so why do we
- // assert the old one's state? Because we are duplicating the old one to
- // the new one, and if the new one must be visible, it's not possible
- // to duplicate an invisible control (the old one) to a visible one
- // (the new one), because that wouldn't be duplication, now, would it?
- //
-
- // else if (!MoreAssert (IsControlVisible (old)))
- // err = paramErr;
- else
- {
- ControlVariant variant = GetControlVariant (old);
- Rect boundsRect = (**old).contrlRect;
-
- *dup = NewControl ((**old).contrlOwner, &boundsRect, "\p", IsControlVisible (old),
- 0, 1, newControlMax, (kControlTabsDefProcResID << 4) | variant, 0);
- if (!*dup)
- err = nilHandleErr;
- else
- {
- if (!(err = CopyTabFontStyle (old,*dup)))
- {
- //
- // Embed duplicate control in old control's super-control.
- // If the old control is in a window without an embedding
- // hierarchy, do nothing.
- //
-
- ControlHandle super;
-
- if (!(err = GetSuperControl (old,&super)))
- err = EmbedControl (*dup,super);
- else if (err == errNoRootControl)
- err = noErr;
-
- //
- // Make sure the old and new controls have the same tab selected.
- //
-
- if (!err)
- SetControlValue (*dup, GetControlValue (old));
- }
-
- if (err)
- {
- DisposeControl (*dup);
- *dup = nil;
- }
- }
- }
-
- return err;
- }
-
- static pascal OSErr CopyTab
- (ControlHandle sourceControl, ControlHandle destControl, UInt16 sourceTab, UInt16 destTab)
- {
- //
- // Copies the tab data from a single tab in one control to a single tab in another control.
- // This is a helper function which is designed to be called from inside a loop.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssert (GetAppearanceVersion ( ) >= 0x0101))
- err = paramErr;
- else if (!MoreAssert (sourceControl && *sourceControl))
- err = nilHandleErr;
- else if (!MoreAssert (destControl && *destControl))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (sourceControl,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (destControl,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssert (sourceTab <= GetControlMaximum (sourceControl)))
- err = paramErr;
- else if (!MoreAssert (destTab <= GetControlMaximum (destControl)))
- err = paramErr;
- else
- {
- Size actualSize;
- ControlTabInfoRec *ctirp = (ControlTabInfoRec *) NewPtr (sizeof (*ctirp));
-
- if (!ctirp)
- err = MemError ( );
- else
- {
- Boolean tabIsEnabled;
-
- ctirp->version = 0;
-
- do
- {
- err = GetControlData (sourceControl,sourceTab,kControlTabInfoTag,sizeof(*ctirp),Ptr(ctirp),&actualSize);
- if (err) break;
- err = SetControlData (destControl,destTab,kControlTabInfoTag,actualSize,Ptr(ctirp));
- if (err) break;
- err = GetControlData (sourceControl,sourceTab,kControlTabEnabledFlagTag,sizeof(tabIsEnabled),Ptr(&tabIsEnabled),&actualSize);
- if (err) break;
- err = SetControlData (destControl,destTab,kControlTabEnabledFlagTag,actualSize,Ptr(&tabIsEnabled));
- if (err) break;
- }
- while (false);
-
- DisposePtr (Ptr (ctirp));
- (void) MoreAssert (noErr == MemError ( ));
- }
- }
-
- return err;
- }
-
- pascal OSErr InsertTab (ControlHandle oldTabs, ControlHandle *dup, UInt16 after)
- {
- //
- // Adds a single tab to a tabs control. Since there are no APIs for adding
- // a tab (except at the end of the list [and that feature is buggy anyway]),
- // we duplicate the entire control with an additional tab, then copy the tab
- // data from the old control to the new control, leaving a gap for the new tab.
- // The after parameter, of course, specifies the tab after which the new tab
- // should appear. 0 is a valid value, even though it does not correspond to
- // any existing tab; it means the new tab should appear first. This function
- // also handles unreasonably high values by assuming you want a tab added after
- // the last existing tab.
- //
-
- OSErr err = noErr;
-
- if (!(MoreAssert (oldTabs && *oldTabs && dup)))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (oldTabs,kControlTabsDefProcResID))
- err = paramErr;
- else
- {
- UInt16 oldMax = GetControlMaximum (oldTabs);
-
- ControlHandle newTabs;
-
- if (!(err = DupTabsControl_Internal (oldTabs, &newTabs, oldMax + 1)))
- {
- if (UInt16 index = oldMax)
- {
- if (after > index) after = index;
-
- if (!(MoreAssert (index >= after)))
- err = paramErr;
- else
- {
- // copy the tab data for the tabs after the new one
-
- while (index > after)
- {
- err = CopyTab (oldTabs,newTabs,index,index+1);
- if (err) break;
- --index;
- }
-
- // copy the tab data for the tabs before the new one
-
- if (!err) while (index)
- {
- err = CopyTab (oldTabs,newTabs,index,index);
- if (err) break;
- --index;
- }
- }
- }
-
- if (err)
- DisposeControl (newTabs);
- else
- {
- short oldValue = GetControlValue (oldTabs);
-
- if (oldValue > after)
- SetControlValue (newTabs, oldValue + 1);
-
- *dup = newTabs;
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr RemoveTab (ControlHandle oldTabs, ControlHandle *dup, UInt16 victim)
- {
- //
- // Removes a single tab from a tabs control. Since there are no APIs for
- // removing an arbitrary tab except at the end of the list, we duplicate
- // the entire control with one fewer tab, then copy the tab data from the
- // old control to the new control, skipping the doomed tab.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (victim && oldTabs && *oldTabs && dup))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (oldTabs,kControlTabsDefProcResID))
- err = paramErr;
- else
- {
- UInt16 max = GetControlMaximum (oldTabs);
-
- if (!MoreAssert (max && max >= victim))
- err = paramErr;
- else
- {
- ControlHandle newTabs;
-
- if (!(err = DupTabsControl_Internal (oldTabs, &newTabs, max)))
- {
- UInt16 index = 1;
-
- // copy the tab data for the tabs before the victim
-
- while (index < victim)
- {
- err = CopyTab (oldTabs,newTabs,index,index);
- if (err) break;
- ++index;
- }
-
- // copy the tab data for the tabs after the victim
-
- if (!err) while (index <= max - 1)
- {
- err = CopyTab (oldTabs, newTabs, index + 1, index);
- if (err) break;
- ++index;
- }
-
- if (err)
- DisposeControl (newTabs);
- else
- {
- SetControlMaximum (newTabs, max - 1);
-
- short oldValue = GetControlValue (oldTabs);
-
- if (oldValue > victim)
- {
- UInt16 newValue = oldValue - 1;
-
- if (newValue != GetControlValue (newTabs))
- SetControlValue (newTabs, newValue);
- }
-
- *dup = newTabs;
- }
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr AppendTabs (ControlHandle control, UInt16 count)
- {
- //
- // The tabs CDEF in Appearance 1.0.X has a fencepost
- // error in which it trashes its private tab data when
- // growing the tabs, so we detect this and refuse to
- // allow it to occur. If you need to add tabs to a tabs
- // control under Appearance 1.0.X, you need to use
- // InsertTab. The API is more cumbersome, but it does
- // work.
- //
-
- OSErr err = noErr;
-
- if (!(MoreAssert (control && *control)))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssert (GetAppearanceVersion ( ) > 0x0101))
- err = paramErr;
- else
- {
- UInt16 max = GetControlMaximum (control);
- SetControlMaximum (control, max + count);
- }
-
- return err;
- }
-
- pascal OSErr TruncateTabs (ControlHandle control, UInt16 count)
- {
- //
- // The tabs CDEF in Appearance 1.0.X has a fencepost
- // error in which it trashes its private tab data when
- // shrinking the tabs, so we detect this and refuse to
- // allow it to occur. If you need to truncate tabs from
- // a tabs control under Appearance 1.0.X, you need to use
- // RemoveTab. The API is more cumbersome, but it does
- // work.
- //
-
- OSErr err = noErr;
-
- if (!(MoreAssert (control && *control)))
- err = nilHandleErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlTabsDefProcResID))
- err = paramErr;
- else if (!MoreAssert (GetAppearanceVersion ( ) > 0x0101))
- err = paramErr;
- else
- {
- UInt16 max = GetControlMaximum (control);
-
- if (!MoreAssert (max && max >= count))
- err = paramErr;
- else
- SetControlMaximum (control, max - count);
- }
-
- return err;
- }
-
- static pascal OSErr SpoofFindControlUnderMouseForTabs
- (Point where, WindowRef window, ControlPartCode *cpc, ControlHandle whichControl)
- {
- //
- // The 1.0.X Tabs control has a bug which causes
- // FindControlUnderMouse to produce kControlNoPart when the
- // mouse is over the current tab. The work-around is a quick
- // and dirty hack we can get away with because it only kicks
- // in under certain (old) versions of the API which we know
- // will never change. When this code was written, the bug had
- // been fixed in a pre-release version of Mac OS.
- // There's no iron-clad guarantee that version will ship with
- // the version number I expect it to, so there is some small but
- // non-zero chance this code may fail to work around the bug
- // if it is present in a system with a version of Appearance
- // greater than 1.0.1.
- //
-
- OSErr err = noErr;
-
- if (*cpc == kControlNoPart && GetAppearanceVersion ( ) <= 0x0101)
- {
- SInt16 contrlValue = (**whichControl).contrlValue;
- (**whichControl).contrlValue = 0;
- ControlHandle newWhichControl = FindControlUnderMouse (where,window,cpc);
- (void) MoreAssert (newWhichControl == whichControl);
- (**whichControl).contrlValue = contrlValue;
- }
-
- return err;
- }
-
- static pascal OSErr SpoofFindControlUnderMouseForPopUpButton (ControlPartCode *cpc)
- {
- //
- // The popup button control has bugs which cause FindControlUnderMouse
- // to produce kControlNoPart when the mouse is over the title and
- // kControlLabelPart when the mouse is over the menu.
- //
-
- OSErr err = noErr;
-
- if (*cpc == kControlLabelPart)
- *cpc = kControlMenuPart;
- else if (*cpc == kControlNoPart)
- *cpc = kControlLabelPart;
-
- return err;
- }
-
- pascal OSErr MoreFindControlUnderMouse
- (Point where, WindowRef window, ControlPartCode *cpc, ControlHandle *whichControl)
- {
- //
- // Second-guesses the results of FindControlUnderMouse for certain controls.
- // Decides which helper function to call based on the control definition
- // procedure resource ID. The truly interesting stuff happens in the helper
- // functions.
- //
-
- OSErr err = noErr;
-
- if (HaveAppearance ( ))
- *whichControl = FindControlUnderMouse (where,window,cpc);
- else
- *cpc = FindControl (where,window,whichControl);
-
- if (*whichControl)
- {
- if (!(MoreAssert (window == (***whichControl).contrlOwner)))
- err = paramErr;
- else
- {
- short resID;
-
- if (!(err = GetControlDefProcResID (*whichControl,&resID)))
- {
- if (HaveAppearance ( ))
- {
- switch (resID)
- {
- case kControlTabsDefProcResID :
-
- err = SpoofFindControlUnderMouseForTabs (where,window,cpc,*whichControl);
- break;
-
- case kControlPopupButtonDefProcResID :
-
- err = SpoofFindControlUnderMouseForPopUpButton (cpc);
- break;
- }
- }
- else
- {
- // here we would work around bugs in pre-Appearance control definitions
- }
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr Get1NewControl (short resID, WindowRef window, ControlHandle *control)
- {
- //
- // Simple glue for Get1Resource. It only does two extra things. It verifies
- // the control resource with the specified exists in the topmost resource
- // file in the search chain and it releases the contol resource after
- // GetNewControl is done with it. I have an aversion to purgeable handles,
- // because they obfuscate leak detection, so I tend to write code like this.
- //
-
- OSErr err = noErr;
-
- Handle controlResource = Get1Resource (kControlTemplateResourceType,resID);
-
- if (!controlResource)
- {
- err = ResError ( );
- if (!err) err = resNotFound;
- }
- else
- {
- *control = GetNewControl (resID,window);
-
- if (!*control)
- err = nilHandleErr;
-
- ReleaseResource (controlResource);
- (void) MoreAssert (ResError ( ) == noErr);
- }
-
- return err;
- }
-
- pascal OSErr SetControlTextFromResource (ControlHandle control, short textResID)
- {
- OSErr err = noErr;
-
- short controlDefProcResID;
-
- if (MoreAssert (!(err = GetControlDefProcResID (control,&controlDefProcResID))))
- {
- if (!MoreAssert (controlDefProcResID == kControlStaticTextDefProcResID || controlDefProcResID == kControlEditTextDefProcResID))
- err = paramErr;
- else
- {
- Handle text = Get1Resource ('TEXT',textResID);
-
- if (!text)
- {
- err = ResError ( );
- if (!err) err = resNotFound;
- }
- else
- {
- Size size = InlineGetHandleSize (text);
-
- if (MoreAssert (MemError ( ) == noErr))
- {
- HLock (text);
-
- if (MoreAssert (MemError ( ) == noErr))
- err = SetControlData (control,kControlNoPart,kControlStaticTextTextTag,size,*text);
- }
-
- ReleaseResource (text);
- (void) MoreAssert (ResError ( ) == noErr);
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr SetControlTextStyleFromResource (ControlHandle control, short resID)
- {
- OSErr err = noErr;
-
- Handle controlStyle = Get1Resource (kMoreControls_ControlStyleType, resID);
-
- if (!controlStyle)
- {
- err = ResError ( );
- if (!err) err = resNotFound;
- }
- else
- {
- Size size = InlineGetHandleSize (controlStyle);
- if (MoreAssert (MemError ( ) == noErr))
- {
- if (!MoreAssert (size == sizeof (ControlFontStyleRec)))
- err = paramErr;
- else
- {
- HLock (controlStyle);
-
- if (MoreAssert (MemError ( ) == noErr))
- err = SetControlFontStyle (control, (const ControlFontStyleRec *) *controlStyle);
- }
- }
-
- ReleaseResource (controlStyle);
- MoreAssert (ResError ( ) == noErr);
- }
-
- return err;
- }
-
- pascal OSErr Get1NewStaticTextControl (short resID, WindowRef window, ControlHandle *control)
- {
- //
- // Since static text controls do not contain data describing their contents
- // or style, this function assumes the calling programmer has created (or chosen
- // not to) text and style resources with the same ID as the control resource.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!(err = Get1NewControl (resID,window,control)))
- {
- err = SetControlTextFromResource (*control,resID);
-
- if (err == resNotFound)
- err = noErr;
-
- if (!err)
- {
- err = SetControlTextStyleFromResource (*control,resID);
-
- if (err == resNotFound)
- err = noErr;
- }
-
- if (err)
- {
- DisposeControl (*control);
- *control = nil;
- }
- }
-
- return err;
- }
-
- pascal OSErr Get1NewPopupButtonControl (short resID, WindowRef window, ControlHandle *control)
- {
- //
- // Some versions of Appearance (as of this writing, 1.0.2 and earlier)
- // have a bug in the popup menu button CDEF which causes a crash on
- // GetBestControlRect if the menu ID specified at creation of the control
- // does not exist (and is not -12345). Luckily, we can test for this
- // condition before it's too late. If the CDEF gets fixed, it's unlikely
- // that the fix will involve setting contrlData to NIL.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!(err = Get1NewControl (resID,window,control)))
- {
- if (!MoreAssertControlHasDefProcResID (*control,kControlPopupButtonDefProcResID))
- err = paramErr;
- else if (!MoreAssert ((***control).contrlData)) // will fire if non-existent menu ID specified
- err = paramErr;
-
- if (err)
- DisposeControl (*control);
- }
-
- return err;
- }
-
- pascal OSErr SetUserPaneDrawProc (ControlHandle control, ControlUserPaneDrawProcPtr upp)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlUserPaneDefProcResID))
- err = paramErr;
- else
- err = SetControlData (control,kControlNoPart,kControlUserPaneDrawProcTag,sizeof(upp),(Ptr)&upp);
-
- return err;
- }
-
- pascal OSErr SetUserPaneSetUpSpecialBackgroundProc (ControlHandle control, ControlUserPaneBackgroundProcPtr upp)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlUserPaneDefProcResID))
- err = paramErr;
- else
- err = SetControlData (control,kControlNoPart,kControlUserPaneBackgroundProcTag,sizeof(upp),(Ptr)&upp);
-
- return err;
- }
-
- static pascal OSErr GetEnclosingBounds (ControlHandle control, Rect *bounds)
- {
- //
- // Gets the bounds of the specified control's super-control.
- // the the specified control has no super-control or the specified
- // control's super control is the root control (whose bounds
- // encompass all of QuickDraw, which is usually not useful), this
- // function gets the bounds of the owning window.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (control && *control && (**control).contrlOwner))
- err = nilHandleErr;
- else if (!HaveAppearance ( ))
- *bounds = ((**control).contrlOwner)->portRect;
- else
- {
- ControlHandle superControl;
-
- err = GetSuperControl (control,&superControl);
-
- if (err == errNoRootControl)
- {
- *bounds = ((**control).contrlOwner)->portRect;
- err = noErr;
- }
- else if (!err)
- {
- ControlHandle rootControl;
-
- if (!(err = GetRootControl ((**control).contrlOwner, &rootControl)))
- {
- if (rootControl == superControl)
- *bounds = ((**control).contrlOwner)->portRect;
- else
- *bounds = (**superControl).contrlRect;
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr ExpandControl (ControlHandle control)
- {
- //
- // Expands the bounds of the specified control to fill its enclosing rectangle.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else
- {
- Rect bounds;
-
- if (!(err = GetEnclosingBounds (control,&bounds)))
- {
- MoveControl (control, bounds.left, bounds.top);
- SizeControl (control, bounds.right - bounds.left, bounds.bottom - bounds.top);
- }
- }
-
- return err;
- }
-
- pascal OSErr InsetControl (ControlHandle control, SInt16 byHowMuch)
- {
- //
- // Insets a control just like InsetRect insets a Rect.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else
- {
- Rect contrlRect = (**control).contrlRect;
-
- InsetRect (&contrlRect, byHowMuch, byHowMuch);
- MoveControl (control, contrlRect.left, contrlRect.top);
- SizeControl (control, contrlRect.right - contrlRect.left, contrlRect.bottom - contrlRect.top);
- }
-
- return err;
- }
-
- pascal OSErr OffsetControl (ControlHandle control, SInt16 h, SInt16 v)
- {
- //
- // Offsets a control just like OffsetRect offsets a Rect.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else
- {
- Rect contrlRect = (**control).contrlRect;
- OffsetRect (&contrlRect,h,v);
- MoveControl (control,contrlRect.left,contrlRect.top);
- }
-
- return err;
- }
-
- pascal OSErr MoveControlNear (ControlHandle moveMe, ControlHandle near, MoreControls_tDirection dir)
- {
- //
- // Moves one control near another. If the controls both have radio behavior,
- // the distance between them is 0. If at least one of the controls does not
- // have radio behavior, the distance between the two controls is non-zero
- // (but not large; see definition of MoreControls_kControlGap).
- //
- // To understand the relative positioning, see the comments in MoreControls_tDirection.
- //
- // Right now this function only supports north, south, east, and west.
- // I can't decide what it means to move a control to the southwest of another.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (moveMe && near && *moveMe && *near))
- err = nilHandleErr;
- else if (!MoreAssert ((**moveMe).contrlOwner == (**near).contrlOwner))
- err = paramErr;
- else if (!MoreAssert (dir == MoreControls_kDirectionNorth || dir == MoreControls_kDirectionSouth ||
- dir == MoreControls_kDirectionEast || dir == MoreControls_kDirectionWest))
- {
- err = paramErr;
- }
- else
- {
- Rect moveMeRect = (**moveMe).contrlRect,
- nearRect = (**near).contrlRect;
- UInt16 moveMeWidth = moveMeRect.right - moveMeRect.left,
- moveMeHeight = moveMeRect.bottom - moveMeRect.top,
- nearWidth = nearRect.right - nearRect.left,
- nearHeight = nearRect.bottom - nearRect.top;
-
- switch (dir)
- {
- case MoreControls_kDirectionNorth :
- case MoreControls_kDirectionSouth :
-
- moveMeRect.left = nearRect.left + (nearWidth / 2) - (moveMeWidth / 2);
- moveMeRect.right = moveMeRect.left + moveMeWidth;
-
- break;
-
- case MoreControls_kDirectionEast :
- case MoreControls_kDirectionWest :
-
- moveMeRect.top = nearRect.top + (nearHeight / 2) - (moveMeHeight / 2);
- moveMeRect.bottom = moveMeRect.top + moveMeHeight;
-
- break;
- }
-
- switch (dir)
- {
- case MoreControls_kDirectionWest :
-
- moveMeRect.right = nearRect.left - MoreControls_kControlGap;
- moveMeRect.left = moveMeRect.right - moveMeWidth;
- break;
-
- case MoreControls_kDirectionEast :
-
- moveMeRect.left = nearRect.right + MoreControls_kControlGap;
- moveMeRect.right = moveMeRect.left + moveMeWidth;
- break;
-
- case MoreControls_kDirectionNorth :
-
- moveMeRect.bottom = nearRect.top - MoreControls_kControlGap;
- moveMeRect.top = moveMeRect.bottom - moveMeHeight;
-
- break;
-
- case MoreControls_kDirectionSouth :
-
- moveMeRect.top = nearRect.bottom + MoreControls_kControlGap;
- moveMeRect.bottom = moveMeRect.top + moveMeHeight;
-
- break;
- }
-
- MoveControl (moveMe, moveMeRect.left, moveMeRect.top); // finally, the pay-off!
- }
-
- return err;
- }
-
- pascal OSErr SetControlQuadrant (ControlHandle control, MoreControls_tDirection quadrant)
- {
- //
- // Moves a control to one of nine quadrants within its enclosing rectangle.
- // To understand the positioning, see the comments in MoreControls_tDirection.
- //
-
- OSErr err = noErr;
-
- if (!(MoreAssert (quadrant >= MoreControls_kDirectionNorthWest || quadrant <= MoreControls_kDirectionSouthEast)))
- err = paramErr;
- else
- {
- Rect enclosingBounds;
-
- if (!(err = GetEnclosingBounds (control,&enclosingBounds)))
- {
- Rect controlRect = (**control).contrlRect;
- UInt16 controlWidth = controlRect.right - controlRect.left,
- controlHeight = controlRect.bottom - controlRect.top,
- enclosingWidth = enclosingBounds.right - enclosingBounds.left,
- enclosingHeight = enclosingBounds.bottom - enclosingBounds.top;
-
- switch (quadrant)
- {
- case MoreControls_kDirectionNorthWest :
- case MoreControls_kDirectionNorth :
- case MoreControls_kDirectionNorthEast :
-
- controlRect.top = enclosingBounds.top;
- controlRect.bottom = enclosingBounds.top + controlHeight;
- break;
-
- case MoreControls_kDirectionSouthWest :
- case MoreControls_kDirectionSouth :
- case MoreControls_kDirectionSouthEast :
-
- controlRect.bottom = enclosingBounds.bottom;
- controlRect.top = enclosingBounds.bottom - controlHeight;
- break;
-
- case MoreControls_kDirectionWest :
- case MoreControls_kDirectionCenter :
- case MoreControls_kDirectionEast :
-
- controlRect.top = enclosingBounds.top + (enclosingHeight / 2) - (controlHeight / 2);
- controlRect.bottom = controlRect.top + controlHeight;
- break;
- }
-
- switch (quadrant)
- {
- case MoreControls_kDirectionNorthWest :
- case MoreControls_kDirectionWest :
- case MoreControls_kDirectionSouthWest :
-
- controlRect.left = enclosingBounds.left;
- controlRect.right = enclosingBounds.left + controlWidth;
- break;
-
- case MoreControls_kDirectionNorthEast :
- case MoreControls_kDirectionEast :
- case MoreControls_kDirectionSouthEast :
-
- controlRect.right = enclosingBounds.right;
- controlRect.left = enclosingBounds.right - controlWidth;
- break;
-
- case MoreControls_kDirectionNorth :
- case MoreControls_kDirectionCenter :
- case MoreControls_kDirectionSouth :
-
- controlRect.left = enclosingBounds.left + (enclosingWidth / 2) - (controlWidth / 2);
- controlRect.right = controlRect.left + controlWidth;
- break;
- }
-
- MoveControl (control, controlRect.left, controlRect.top);
- }
- }
-
- return err;
- }
-
- pascal OSErr SetBestControlRect (ControlHandle control, SInt16 *baseLineOffsetP)
- {
- //
- // Takes GetBestControlRect to its logical conclusion and moves and resizes
- // the specified control to fit its best control bounds rectangle, if any.
- // You can pass NIL for baseLineOffsetP if you don't care to know the text
- // baseline for the control. This function should probably produce a value
- // denoting whether the control moved or changed size.
- //
-
- OSErr err = noErr;
-
- // it's OK for baseLineOffsetP to be NIL
-
- if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else
- {
- UInt32 features;
- err = GetControlFeatures (control, &features);
-
- if (!err && (kControlSupportsCalcBestRect & features))
- {
- Rect best = { 0,0,0,0 };
- SInt16 dontCare;
-
- if (!baseLineOffsetP)
- baseLineOffsetP = &dontCare;
-
- if (!(err = GetBestControlRect (control,&best,baseLineOffsetP)))
- {
- SizeControl (control, best.right - best.left, best.bottom - best.top);
- MoveControl (control, best.left, best.top);
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr GetStaticTextControlTextHeight (ControlHandle control, SInt16 *textHeight)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlStaticTextDefProcResID))
- err = paramErr;
- else
- {
- Size actualTextHeightSize;
- err = GetControlData (control, kControlNoPart, kControlStaticTextTextHeightTag,
- sizeof (textHeight), (Ptr) textHeight, &actualTextHeightSize);
- if (!err) (void) MoreAssert (actualTextHeightSize == sizeof (*textHeight));
- }
-
- return err;
- }
-
- pascal OSErr SetBevelButtonMenu (ControlHandle control, MenuRef menu)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlBevelButtonDefProcResID))
- err = paramErr;
- else
- {
- //
- // There appears to be a bug in the bevel button CDEF which prevents you
- // from setting a menu if the control was not created with a menu, so to
- // avoid this problem, we assert so you can tell when you are likely to
- // run afoul of this problem. I can't remember whether I filed a bug
- // against this misbehavior. I should check.
- //
-
- #if MORE_DEBUG
-
- MenuHandle existingMenuH;
- Size actualSize;
-
- err = GetControlData (control, kControlNoPart, kControlBevelButtonMenuHandleTag,
- sizeof(existingMenuH), Ptr (&existingMenuH), &actualSize);
- if (err) return err;
- if (!MoreAssert (actualSize == sizeof(existingMenuH)))
- err = paramErr;
- else if (!MoreAssert (existingMenuH))
- err = nilHandleErr;
- else
-
- #endif
-
- err = SetControlData (control, kControlNoPart, kControlBevelButtonMenuHandleTag,
- sizeof(MenuRef), Ptr (&menu));
- }
-
- return err;
- }
-
- pascal OSErr SetPopUpButtonMenu (ControlHandle control, MenuRef menu)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- MoreAssert (HaveAppearance ( ));
- MoreAssert (GetAppearanceVersion ( ) >= 0x0101);
- MoreAssertControlHasDefProcResID (control,kControlPopupButtonDefProcResID);
-
- OSErr err = SetControlData (control, kControlNoPart, kControlPopupButtonMenuHandleTag,
- sizeof(MenuRef), Ptr (&menu));
- return err;
- }
-
- pascal OSErr SetBevelButtonMenuDelay (ControlHandle control, SInt32 delay)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssert (GetAppearanceVersion ( ) >= 0x0101))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlBevelButtonDefProcResID))
- err = paramErr;
- else
- err = SetControlData (control, kControlNoPart, kControlBevelButtonMenuDelayTag, sizeof (delay), Ptr (&delay));
-
- return err;
- }
-
- pascal OSErr SetProgressBarIndeterminate (ControlHandle control, Boolean i)
- {
- //
- // This is just convenience glue to avoid stringing a bunch of long
- // constant names together all the time.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (!MoreAssertControlHasDefProcResID (control,kControlProgressBarDefProcResID))
- err = paramErr;
- else if (!MoreAssert (i == true || i == false)) // talk about paranoid!
- err = paramErr;
- else
- err = SetControlData (control, kControlNoPart, kControlProgressBarIndeterminateTag, sizeof (i), Ptr (&i));
-
- return err;
- }
-
- pascal OSErr ToggleControl (ControlHandle control)
- {
- //
- // Given a control whose limits suggest it toggles between 0 and 1
- // (like a check box or a radio button), this function sets the control
- // value to the opposite of its present value.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (control && *control))
- err = nilHandleErr;
- else if (!MoreAssert (GetControlMaximum (control) == 1))
- err = paramErr;
- else if (!MoreAssert (GetControlMinimum (control) == 0))
- err = paramErr;
- else
- SetControlValue (control, GetControlValue (control) ? 0 : 1);
-
- return err;
- }
-
- static pascal OSErr EmbedSubControls (ControlHandle source, ControlHandle destination, UInt16 index)
- {
- //
- // This is a helper function for EncloseSubControls; if you find a use
- // for it elsewhere, keep in mind that the controls are embedded into
- // the destination control in the opposite order from that in which
- // they appear in the source control. This is fine as long as you
- // copy the controls back with EmbedSubControls. This is just what
- // EncloseSubControls needed. Why do we do things this way? We want
- // to be recursive so we can easily back out of a partial embedding
- // transfer, and this is the easiest way to do it.
- //
-
- OSErr err = noErr;
-
- if (index)
- {
- ControlHandle subControl;
-
- if (!(err = GetIndexedSubControl (source,index,&subControl)))
- if (!(err = EmbedControl (subControl,destination)))
- {
- err = EmbedSubControls (source,destination,index-1);
- if (err) (void) EmbedControl (subControl,source);
- }
- }
-
- return err;
- }
-
- pascal OSErr EncloseSubControls (ControlHandle parent)
- {
- //
- // Moves and resizes the parent control to enclose all its sub-controls.
- // However, we can't just move the parent control, because the
- // sub-controls will move along with it, which is not what we want.
- // So we create a temporary embeddable control and move the sub-controls
- // to this temporary control while we move the parent control.
- // Note that EmbedSubControls reverses the order of the sub-controls,
- // which is fine for our purposes, since we call it twice.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (parent && *parent))
- err = nilHandleErr;
- else
- {
-
- UInt16 subControlCount;
-
- if (!(err = CountSubControls (parent,&subControlCount)))
- {
- if (!MoreAssert (subControlCount > 0))
- err = paramErr;
- else
- {
- static Rect tempUserPaneBounds;
-
- ControlHandle tempUserPane = NewControl ((**parent).contrlOwner, &tempUserPaneBounds, "\p", false,
- kControlSupportsEmbedding, 0, 0, kControlUserPaneProc, 0);
-
- if (!tempUserPane)
- err = nilHandleErr;
- else
- {
- UInt16 subControlIndex = subControlCount;
- ControlHandle subControl;
-
- if (!(err = GetIndexedSubControl (parent,subControlIndex,&subControl)))
- {
- if (!MoreAssert (subControl && *subControl))
- err = nilHandleErr;
- else
- {
- Rect parentRect = (**subControl).contrlRect;
-
- while (--subControlIndex)
- {
- err = GetIndexedSubControl (parent,subControlIndex,&subControl);
- if (err) break;
-
- if (!MoreAssert (subControl && *subControl))
- {
- err = nilHandleErr;
- break;
- }
-
- Rect contrlRect = (**subControl).contrlRect;
-
- if (contrlRect.bottom > parentRect.bottom)
- parentRect.bottom = contrlRect.bottom;
- if (contrlRect.right > parentRect.right)
- parentRect.right = contrlRect.right;
- if (contrlRect.left < parentRect.left)
- parentRect.left = contrlRect.left;
- if (contrlRect.top < parentRect.top)
- parentRect.top = contrlRect.top;
- }
-
- if (!err && !(err = EmbedSubControls (parent,tempUserPane,subControlCount)))
- {
- InsetRect (&parentRect, -(MoreControls_kControlGap), -(MoreControls_kControlGap));
- MoveControl (parent, parentRect.left, parentRect.top);
- SizeControl (parent, parentRect.right - parentRect.left, parentRect.bottom - parentRect.top);
- OSErr err2 = EmbedSubControls (tempUserPane,parent,subControlCount);
- if (!err) err2 = err;
- }
- }
- }
- DisposeControl (tempUserPane);
- }
- }
- }
- }
- return err;
- }
-
- pascal OSErr AlignControl (ControlHandle anchor, ControlHandle moveMe, MoreControls_tAlignment align)
- {
- //
- // Aligns one control (moveMe) to an edge of another (anchor).
- // For an explanation of MoreControls_tAlignment, see the header.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (moveMe && *moveMe && anchor && *anchor))
- err = nilHandleErr;
- else if (!MoreAssert (align == MoreControls_kAlignSystem || align == MoreControls_kAlignLeft ||
- align == MoreControls_kAlignCenter || align == MoreControls_kAlignRight))
- {
- err = paramErr;
- }
- else
- {
- align = FilterAlignment (align);
-
- if (!MoreAssert (align == MoreControls_kAlignLeft ||
- align == MoreControls_kAlignCenter || align == MoreControls_kAlignRight))
- {
- err = paramErr;
- }
- else
- {
- short horiz, vert = (**moveMe).contrlRect.top;
-
- switch (align)
- {
- case MoreControls_kAlignLeft :
-
- horiz = (**anchor).contrlRect.left;
- break;
-
- case MoreControls_kAlignCenter :
-
- (void) MoreAssert (false && MoreControls_kAlignCenter); // untraced logic
- break;
-
- case MoreControls_kAlignRight :
-
- (void) MoreAssert (false && MoreControls_kAlignRight); // untraced logic
- horiz = (**anchor).contrlRect.right -
- ((**moveMe).contrlRect.right - (**moveMe).contrlRect.left);
- break;
- }
-
- MoveControl (moveMe, horiz, vert);
- }
- }
-
- return err;
- }
-
- pascal OSErr AlignSubControls (ControlHandle parent, MoreControls_tAlignment align)
- {
- //
- // Given a parent control, aligns all its sub-controls along the most
- // extreme edge. So if left alignment is specified, this function finds
- // the sub-control which is leftmost and aligns the rest of the sub-controls
- // to its left edge. For an explanation of MoreControls_tAlignment, see the header.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (parent && *parent))
- err = nilHandleErr;
- else if (!MoreAssert (align == MoreControls_kAlignSystem || align == MoreControls_kAlignLeft ||
- align == MoreControls_kAlignCenter || align == MoreControls_kAlignRight))
- {
- err = paramErr;
- }
- else
- {
- align = FilterAlignment (align);
-
- if (!MoreAssert (align == MoreControls_kAlignLeft ||
- align == MoreControls_kAlignCenter || align == MoreControls_kAlignRight))
- {
- err = paramErr;
- }
- else
- {
-
- UInt16 subControlCount;
-
- if (!(err = CountSubControls (parent,&subControlCount)))
- {
- if (!MoreAssert (subControlCount > 0))
- err = paramErr;
- else if (subControlCount == 1)
- {
- (void) MoreAssert (false && subControlCount == 1); // untraced logic
- }
- else
- {
- UInt16 subControlIndex = subControlCount;
- ControlHandle subControl;
-
- if (!(err = GetIndexedSubControl (parent,subControlIndex,&subControl)))
- {
- if (!MoreAssert (subControl && *subControl))
- err = nilHandleErr;
- else
- {
- ControlHandle anchor = subControl;
-
- while (--subControlIndex)
- {
- err = GetIndexedSubControl (parent,subControlIndex,&subControl);
- if (err) break;
-
- switch (align)
- {
- case MoreControls_kAlignLeft :
-
- if ((**subControl).contrlRect.left < (**anchor).contrlRect.left)
- anchor = subControl;
- break;
-
- case MoreControls_kAlignCenter :
-
- (void) MoreAssert (false && MoreControls_kAlignCenter); // untraced logic
- break;
-
- case MoreControls_kAlignRight :
-
- if ((**subControl).contrlRect.right > (**anchor).contrlRect.right)
- anchor = subControl;
- break;
- }
- }
-
- if (!err)
- {
- subControlIndex = subControlCount;
-
- do
- {
- err = GetIndexedSubControl (parent,subControlIndex,&subControl);
- if (err) break;
-
- if (subControl != anchor)
- {
- short horiz, vert = (**subControl).contrlRect.top;
-
- switch (align)
- {
- case MoreControls_kAlignLeft :
-
- horiz = (**anchor).contrlRect.left;
- break;
-
- case MoreControls_kAlignCenter :
-
- (void) MoreAssert (false && MoreControls_kAlignCenter); // untraced logic
- break;
-
- case MoreControls_kAlignRight :
-
- horiz = (**anchor).contrlRect.right -
- ((**subControl).contrlRect.right - (**subControl).contrlRect.left);
- break;
- }
-
- MoveControl (subControl,horiz,vert);
- }
- }
- while (--subControlIndex);
- }
- }
- }
- }
- }
- }
- }
-
- return err;
- }
-
- pascal OSErr IdleControlsInAllWindows (void)
- {
- //
- // For each visible window in the window list, this function gives
- // the controls a chance to idle.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (HaveAppearance ( )))
- err = paramErr;
- else if (WindowPtr window = FrontWindow ( ))
- {
- IdleControls (window);
-
- window = GetNextWindow (window);
-
- while (window)
- {
- if (IsWindowVisible (window))
- IdleControls (window);
-
- window = GetNextWindow (window);
- }
- }
-
- return err;
- }
-
- pascal OSErr SetCursorAccordingToControl (QDGlobalsPtr qd)
- {
- //
- // Sets the cursor according to which control the cursor
- // is floating over. In a perfect world, we'd be able to
- // ask the control to set the cursor for us, but in the
- // real world we just guess.
- //
-
- OSErr err = noErr;
-
- WindowPtr window = FrontWindow ( );
-
- if (!window)
- SetCursor (&(qd->arrow));
- else
- {
- GrafPtr preservedPort;
-
- GetPort (&preservedPort);
- SetPort (window);
-
- Point mouse;
- GetMouse (&mouse);
-
- ControlPartCode cpc;
- ControlHandle whichControl;
-
- err = MoreFindControlUnderMouse (mouse, window, &cpc, &whichControl);
-
- if (!err)
- {
- if (!whichControl || cpc == kControlNoPart || !HaveAppearance ( ))
- SetCursor (&(qd->arrow));
- else
- {
- short resID;
-
- if (!(err = GetControlDefProcResID (whichControl, &resID)))
- {
- if (resID == kControlEditTextDefProcResID)
- SetCursor (*GetCursor (iBeamCursor));
- else
- SetCursor (&(qd->arrow));
- }
- }
- }
-
- SetPort (preservedPort);
- }
-
- return err;
- }
-
- pascal OSErr IsScrollBar (ControlHandle ch, Boolean *isScrollBar)
- {
- //
- // Tests whether a given control is a scroll bar.
- // Replaces bogus code from AppsToGo. TO DO: find
- // a better abstraction for this. Waiting for
- // developer feedback. This function may go away.
- //
-
- OSErr err = noErr;
-
- if (!MoreAssert (ch && *ch && isScrollBar))
- err = nilHandleErr;
- else
- {
- short resID;
-
- if (!(err = GetControlDefProcResID (ch, &resID)))
- {
- *isScrollBar = (resID == kControlOldScrollBarDefProcResID || resID == kControlScrollBarDefProcResID);
- }
- }
-
- return err;
- }
-